<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>cltexture2d.cpp Example File (mandelbrot/cltexture2d.cpp)</title>
  <link rel="stylesheet" type="text/css" href="style/style.css" />
  <script src="scripts/jquery.js" type="text/javascript"></script>
  <script src="scripts/functions.js" type="text/javascript"></script>
  <script src="./scripts/superfish.js" type="text/javascript"></script>
  <link rel="stylesheet" type="text/css" href="style/superfish.css" />  <script src="./scripts/narrow.js" type="text/javascript"></script>
  <link rel="stylesheet" type="text/css" href="style/narrow.css" />
  <!--[if IE]>
<meta name="MSSmartTagsPreventParsing" content="true">
<meta http-equiv="imagetoolbar" content="no">
<![endif]-->
<!--[if lt IE 7]>
<link rel="stylesheet" type="text/css" href="style/style_ie6.css">
<![endif]-->
<!--[if IE 7]>
<link rel="stylesheet" type="text/css" href="style/style_ie7.css">
<![endif]-->
<!--[if IE 8]>
<link rel="stylesheet" type="text/css" href="style/style_ie8.css">
<![endif]-->
</head>
<body class="" onload="CheckEmptyAndLoadList();">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td align="left" valign="top" width="150"><img src="images/qt-logo.png" align="left" border="0" />&nbsp;&nbsp;<img src="images/qtopencl-logo.png" border="0" /></td>
<td width="1">&nbsp;&nbsp;</td><td class="postheader" valign="center"> <a href="index.html"><font color="#004faf">Home</font></a>&nbsp;&middot; <a href="qtopencl-all-classes.html"><font color="#004faf">All Classes</font></a></td>
</table><h1 class="title">cltexture2d.cpp Example File</h1>
<span class="small-subtitle">mandelbrot/cltexture2d.cpp</span>
<!-- $$$mandelbrot/cltexture2d.cpp-description -->
<div class="descr"> <a name="details"></a>
<pre class="highlightedCode brush: cpp"><span class="comment">    /****************************************************************************
    **
    ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
    ** All rights reserved.
    ** Contact: Nokia Corporation (qt-info@nokia.com)
    **
    ** This file is part of the QtOpenCL module of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:LGPL$
    ** No Commercial Usage
    ** This file contains pre-release code and may not be distributed.
    ** You may use this file in accordance with the terms and conditions
    ** contained in the Technology Preview License Agreement accompanying
    ** this package.
    **
    ** GNU Lesser General Public License Usage
    ** Alternatively, this file may be used under the terms of the GNU Lesser
    ** General Public License version 2.1 as published by the Free Software
    ** Foundation and appearing in the file LICENSE.LGPL included in the
    ** packaging of this file.  Please review the following information to
    ** ensure the GNU Lesser General Public License version 2.1 requirements
    ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    **
    ** In addition, as a special exception, Nokia gives you certain additional
    ** rights.  These rights are described in the Nokia Qt LGPL Exception
    ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    **
    ** If you have questions regarding the use of this file, please contact
    ** Nokia at qt-info@nokia.com.
    **
    **
    **
    **
    **
    **
    **
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/</span>

    #include &quot;cltexture2d.h&quot;
    #include &quot;qclcontextgl.h&quot;
    #include &quot;glproxy.h&quot;
    #if QT_VERSION &gt;= 0x040700 &amp;&amp; !defined(QT_OPENGL_ES)
    #include &lt;QtOpenGL/qglbuffer.h&gt;
    #define USE_PIXEL_UNPACK_BUFFERS 1
    #endif

<span class="comment">    /*!
        \class CLTexture2D
        \brief The CLTexture2D class represents a 2D OpenCL texture object.
        \since 4.7
        \ingroup openclgl

        Normally applications render into OpenGL textures by calling
        QCLContextGL::createTexture2D() to wrap an existing texture identifier
        with a QCLImage2D object.  However, some systems do not support
        the OpenCL/OpenGL sharing mechanisms that are needed to make that work.

        CLTexture2D abstracts the creation and management of \c{GL_RGBA}
        textures so that applications can render into them with OpenCL
        kernels without needing to implement special handling for
        OpenCL implementations that lack sharing.
    */</span>

    class CLTexture2DPrivate : public QObject
    {
        Q_OBJECT
    public:
        CLTexture2DPrivate()
            : context(0)
            , clContext(0)
            , textureId(0)
            , directRender(false)
    #ifdef USE_PIXEL_UNPACK_BUFFERS
            , pixelBuffer(0)
    #endif
        {
        }
        ~CLTexture2DPrivate()
        {
    #ifdef USE_PIXEL_UNPACK_BUFFERS
            delete pixelBuffer;
    #endif
        }

        const QGLContext *context;
        QCLContextGL *clContext;
        GLuint textureId;
        QSize size;
        bool directRender;
    #ifdef USE_PIXEL_UNPACK_BUFFERS
        QGLBuffer *pixelBuffer;
    #endif

        void setContextAndId(const QGLContext *ctx, GLuint id);

    private slots:
        void aboutToDestroyContext(const QGLContext *ctx);
    };

    void CLTexture2DPrivate::aboutToDestroyContext(const QGLContext *ctx)
    {
        if (context == ctx) {
            context = 0;
            textureId = 0;
        }
    }

    void CLTexture2DPrivate::setContextAndId(const QGLContext *ctx, GLuint id)
    {
        context = ctx;
        textureId = id;
        connect(QGLSignalProxy::instance(),
                SIGNAL(aboutToDestroyContext(const QGLContext *)),
                this,
                SLOT(aboutToDestroyContext(const QGLContext *)));
    }

<span class="comment">    /*!
        Constructs an uninitialized OpenCL texture object.
    */</span>
    CLTexture2D::CLTexture2D()
        : QCLImage2D(), d_ptr(new CLTexture2DPrivate())
    {
    }

<span class="comment">    /*!
        Destroys this OpenCL texture object.
    */</span>
    CLTexture2D::~CLTexture2D()
    {
        destroy();
    }

<span class="comment">    /*!
        Constructs an OpenCL texture of \a size in \a context.
        Returns true if the texture was created; false otherwise.

        \sa destroy(), textureId()
    */</span>
    bool CLTexture2D::create(QCLContextGL *context, const QSize &amp;size)
    {
        Q_D(CLTexture2D);
        Q_ASSERT(context &amp;&amp; size.width() &gt; 0 &amp;&amp; size.height() &gt; 0);
        Q_ASSERT(memoryId() == 0);    <span class="comment">// Must not be created already.</span>
        d-&gt;clContext = context;

        <span class="comment">// Create the texture in the GL context.</span>
        GLuint textureId;
        glGenTextures(1, &amp;textureId);
        glBindTexture(GL_TEXTURE_2D, textureId);
    #ifdef GL_CLAMP_TO_EDGE
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    #else
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    #endif
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0,
                     GL_RGBA, GL_UNSIGNED_BYTE, 0);
        glBindTexture(GL_TEXTURE_2D, 0);

        <span class="comment">// If the context supports object sharing, then this is really easy.</span>
        if (context-&gt;supportsObjectSharing()) {
            QCLImage2D image = context-&gt;createTexture2D
                (GL_TEXTURE_2D, textureId, 0, QCLMemoryObject::WriteOnly);
            if (image.isNull()) {
                glDeleteTextures(1, &amp;textureId);
                return false;
            }
            d-&gt;setContextAndId(QGLContext::currentContext(), textureId);
            setId(image.context(), image.memoryId());
            d-&gt;size = size;
            d-&gt;directRender = true;
            return true;
        }

    #ifdef USE_PIXEL_UNPACK_BUFFERS
        <span class="comment">// Create a pixel unpack buffer for downloading image data</span>
        <span class="comment">// out of OpenCL and uploading it into OpenGL.</span>
        d-&gt;pixelBuffer = new QGLBuffer(QGLBuffer::PixelUnpackBuffer);
        d-&gt;pixelBuffer-&gt;setUsagePattern(QGLBuffer::DynamicDraw);
        if (d-&gt;pixelBuffer-&gt;create()) {
            d-&gt;pixelBuffer-&gt;bind();
            d-&gt;pixelBuffer-&gt;allocate(size.width() * size.height() * 4);
            d-&gt;pixelBuffer-&gt;release();
        } else {
            delete d-&gt;pixelBuffer;
            d-&gt;pixelBuffer = 0;
        }
    #endif

        <span class="comment">// Create a 2D image in the OpenCL device for rendering with OpenCL.</span>
        QCLImage2D image = context-&gt;createImage2DDevice
            (QCLImageFormat(QCLImageFormat::Order_RGBA,
                            QCLImageFormat::Type_Normalized_UInt8),
             size, QCLMemoryObject::WriteOnly);
        if (image.isNull()) {
            glDeleteTextures(1, &amp;textureId);
    #ifdef USE_PIXEL_UNPACK_BUFFERS
            delete d-&gt;pixelBuffer;
            d-&gt;pixelBuffer = 0;
    #endif
            return false;
        }
        d-&gt;setContextAndId(QGLContext::currentContext(), textureId);
        setId(image.context(), image.memoryId());
        d-&gt;size = size;
        d-&gt;directRender = false;
        return true;
    }

<span class="comment">    /*!
        \fn bool CLTexture2D::create(QCLContextGL *context, int width, int height)
        \overload

        Constructs an OpenCL texture of size (\a width, \a height)
        in \a context.  Returns true if the texture was created; false otherwise.

        \sa destroy()
    */</span>

<span class="comment">    /*!
        Destroys this OpenCL texture object.
    */</span>
    void CLTexture2D::destroy()
    {
        Q_D(CLTexture2D);
        setId(0, 0);
        GLuint textureId = d-&gt;textureId;
        if (textureId) {
            QGLContext *oldContext;
            QGLContext *currentContext = const_cast&lt;QGLContext *&gt;(QGLContext::currentContext());
            if (currentContext != d-&gt;context &amp;&amp; !QGLContext::areSharing(d-&gt;context, currentContext)) {
                oldContext = currentContext;
                const_cast&lt;QGLContext *&gt;(d-&gt;context)-&gt;makeCurrent();
            } else {
                oldContext = 0;
            }
            glDeleteTextures(1, &amp;textureId);
            if (oldContext)
                oldContext-&gt;makeCurrent();
        }
    #ifdef USE_PIXEL_UNPACK_BUFFERS
        delete d-&gt;pixelBuffer;
        d-&gt;pixelBuffer = 0;
    #endif
        d-&gt;context = 0;
        d-&gt;textureId = 0;
        d-&gt;size = QSize();
        d-&gt;directRender = false;
    }

<span class="comment">    /*!
        Acquires access to this texture so that OpenCL kernels
        can render into it.  OpenGL cannot use the texture until
        release() is called.

        \sa release()
    */</span>
    void CLTexture2D::acquire()
    {
        Q_D(CLTexture2D);
        if (d-&gt;directRender)
            d-&gt;clContext-&gt;acquire(*this).waitForFinished();
    }

<span class="comment">    /*!
        Releases access to this texture so that OpenGL can use it again.
        The textureId() will also be bound to the current OpenGL context.

        \sa acquire()
    */</span>
    void CLTexture2D::release()
    {
        Q_D(CLTexture2D);
        if (!d-&gt;textureId)
            return;

        <span class="comment">// If we are doing direct rendering, then just release the OpenCL object.</span>
        if (d-&gt;directRender) {
            d-&gt;clContext-&gt;release(*this).waitForFinished();
            glBindTexture(GL_TEXTURE_2D, d-&gt;textureId);
            return;
        }

        <span class="comment">// Wait for the current OpenCL commands to finish.</span>
        context()-&gt;marker().waitForFinished();

        <span class="comment">// Upload the contents of the OpenCL buffer into the texture.</span>
        void *ptr;
    #ifdef USE_PIXEL_UNPACK_BUFFERS
        if (d-&gt;pixelBuffer) {
            d-&gt;pixelBuffer-&gt;bind();
            ptr = d-&gt;pixelBuffer-&gt;map(QGLBuffer::ReadWrite);
            if (ptr) {
                read(ptr, QRect(QPoint(0, 0), d-&gt;size), d-&gt;size.width() * 4);
                d-&gt;pixelBuffer-&gt;unmap();
                glBindTexture(GL_TEXTURE_2D, d-&gt;textureId);
                glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
                                d-&gt;size.width(), d-&gt;size.height(),
                                GL_RGBA, GL_UNSIGNED_BYTE, 0);
                d-&gt;pixelBuffer-&gt;release();
                return;
            }
            <span class="comment">// Pixel buffer cannot be mapped, so it is of no use to us.</span>
            d-&gt;pixelBuffer-&gt;release();
            delete d-&gt;pixelBuffer;
            d-&gt;pixelBuffer = 0;
        }
    #endif
        ptr = map(QRect(QPoint(0, 0), d-&gt;size), QCLMemoryObject::ReadOnly);
        glBindTexture(GL_TEXTURE_2D, d-&gt;textureId);
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
                        d-&gt;size.width(), d-&gt;size.height(),
                        GL_RGBA, GL_UNSIGNED_BYTE, ptr);
        unmap(ptr);
    }

<span class="comment">    /*!
        Returns the OpenGL texture identifier for this OpenCL texture object.
    */</span>
    GLuint CLTexture2D::textureId() const
    {
        Q_D(const CLTexture2D);
        return d-&gt;textureId;
    }


    #include &quot;cltexture2d.moc&quot;</pre>
</div>
<!-- @@@mandelbrot/cltexture2d.cpp -->
<p /><address><hr /><div align="center">
<table width="100%" cellspacing="0" border="0"><tr class="address">
<td align="left">Copyright &copy; 2010 Nokia Corporation</td>
<td align="right">QtOpenCL Documentation</td>
</tr></table></div></address>  <script src="scripts/functions.js" type="text/javascript"></script>
  <script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-4457116-5']);
  _gaq.push(['_trackPageview']);
  (function() {
  var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();
  </script>
</body>
</html>
